package acm.account.l2j;
/**
 * @author Emporeo
 * @web http://www.fai-communication.de/accountManager
 * @web source: http://code.google.com/p/mmo-account-manager/
 */

/*
 * Add/Update/Delete Methods are directly from package
 * net.sf.l2j.accountmanager: Class: SQLAccountManager
 * Need to rewrite/modify caused by another CON instance 
 */
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import javolution.util.FastList;
import acm.functions.Base64;


import acm.account.Account;

public class Account_L2J extends Account {

	public Account_L2J() {
		super();
	}

	public Account_L2J(ServletContext context) {
		super(context);
	}
	
	
	/**
	 * Validate the login
	 * @param login
	 * @param password
	 * @return
	 */
	public boolean isLoginValid(String login, String password){
		
		try
		{
			MessageDigest md = MessageDigest.getInstance("SHA");
			byte[] raw = password.getBytes("UTF-8");
			byte[] hash = md.digest(raw);
			
			byte[] expected = null;
			String encodedPassword = Base64.encodeBytes(hash);
			
			con = dao.getDataSourceConnection(getContext());
			PreparedStatement statement = con.prepareStatement("SELECT password, accessLevel, lastServer FROM accounts WHERE login=? AND password=?");
			statement.setString(1, login);
			statement.setString(2, encodedPassword);
			ResultSet rset = statement.executeQuery();
//			 debug
			//context.log("Login: " + login + " - " + "Password: " + encodedPassword);
			if (rset.next())
			{
				expected = Base64.decode(rset.getString("password"));
				//access = rset.getInt("accessLevel");
				//lastServer = rset.getInt("lastServer");
			}
			rset.close();
			statement.close();
			
//			 if account doesnt exists
			if (expected == null){
				return false;
			}else{
				return true;
			}
			
		}catch(SQLException SQLe){
			context.log(this.getClass().getName() + " - Method:isLoginValid: "  + SQLe.getLocalizedMessage());
			this.setError(SQLe.getLocalizedMessage());
			return false;
		}catch(Exception e){
			this.setError(e.toString());
			context.log(this.getClass().getName() + " - Method:isLoginValid: "  + e.getMessage());
			return false;
		}
		finally{
	    	try{stmt.close();}catch(Exception ex){};
	        try{con.close();}catch(Exception ex){};
		}
			
	}
	
	
	
	
	/**
	 * Add or Update a new L2J account
	 * @param account - login Name
	 * @param password
	 * @param level - access level
	 * @throws IOException
	 * @throws SQLException
	 * @throws NoSuchAlgorithmException
	 */
	protected void doAddOrUpdateAccount(String account,String password, String level) throws IOException, SQLException, NoSuchAlgorithmException
    {
		
		try{
        // Encode Password
        MessageDigest md = MessageDigest.getInstance("SHA");
        byte[] newpass;
        newpass = password.getBytes("UTF-8");
        newpass = md.digest(newpass);
        
        con = dao.getDataSourceConnection(getContext());
        PreparedStatement statement = con.prepareStatement("REPLACE	accounts (login, password, accessLevel) VALUES (?,?,?)");
        statement.setString(1, account);
        statement.setString(2, Base64.encodeBytes(newpass));
        statement.setString(3, level);
        statement.executeUpdate();
        statement.close();
        con.close();
   
		}catch(SQLException SQLe){
			context.log(this.getClass().getName() + " - Method:doGetAllCharacters: "  + SQLe.getLocalizedMessage());
			this.setError(SQLe.getLocalizedMessage());
		}catch(Exception e){
			this.setError(e.toString());
			context.log(this.getClass().getName() + " - Method:doGetAllCharacters: "  + e.getMessage());
		}
		finally{
	    	try{stmt.close();}catch(Exception ex){};
	        try{con.close();}catch(Exception ex){};
		}
	}
	
	
	/**
	 * Creates a new L2J account
	 * @param account
	 * @param password
	 * @param level
	 * @param accessLevel
	 * @param request
	 * @throws IOException
	 * @throws SQLException
	 * @throws NoSuchAlgorithmException
	 */
	protected void doCreateAccount(String account,String password, String level, int accessLevel, HttpServletRequest request) throws IOException, SQLException, NoSuchAlgorithmException
    {
		
		try{
			MessageDigest md = MessageDigest.getInstance("SHA");
			byte[] raw = password.getBytes("UTF-8");
			byte[] hash = md.digest(raw);
		
			//int lastServer = 1;
			
			con = dao.getDataSourceConnection(getContext());
			
			//if ((account.length() >= 2) && (account.length() <= 14))

				PreparedStatement statement = con.prepareStatement("INSERT INTO accounts (login,password,lastactive,accessLevel,lastIP) values(?,?,?,?,?)");
				statement.setString(1, account);
				statement.setString(2, Base64.encodeBytes(hash));
				statement.setLong(3, System.currentTimeMillis());
				statement.setInt(4, accessLevel);
				statement.setString(5, request.getRemoteAddr());
				statement.execute();
				statement.close();
				
   
		}catch(SQLException SQLe){
			context.log(this.getClass().getName() + " - Method:doCreateAccount: "  + SQLe.getLocalizedMessage());
			this.setError(SQLe.getLocalizedMessage());
		}catch(Exception e){
			this.setError(e.toString());
			context.log(this.getClass().getName() + " - Method:doCreateAccount: "  + e.getMessage());
		}
		finally{
	    	try{stmt.close();}catch(Exception ex){};
	        try{con.close();}catch(Exception ex){};
		}
	}
	
	
	/**
	 * Change Access Level of Account
	 * @param account - loginName
	 * @param level - access Level
	 * @throws SQLException
	 */
	protected void doChangeAccountLevel(String account, String level) throws SQLException
    {
		try{
        con = dao.getDataSourceConnection(getContext());
        
        // Check Account Exist
        PreparedStatement statement = con.prepareStatement("SELECT COUNT(*) FROM accounts WHERE login=?;");
        statement.setString(1, account);
        ResultSet rset = statement.executeQuery();
        if(rset.next()==false) {
            System.out.println("False");
            
        } else if(rset.getInt(1)>0) {
            
            // Exist
            
            // Update
            statement = con.prepareStatement("UPDATE accounts SET accessLevel=? WHERE login=?;");
            statement.setEscapeProcessing(true);
            statement.setString(1, level);
            statement.setString(2, account);
            statement.executeUpdate();
            
            System.out.println("Account " + account + " has been updated.");
        } else {
            // Not Exist
            System.out.println("Account " + account + " does not exist.");
        }
        rset.close();
        statement.close();
        con.close();
        
		}catch(SQLException SQLe){
			context.log(this.getClass().getName() + " - Method:doGetAllCharacters: "  + SQLe.getLocalizedMessage());
			this.setError(SQLe.getLocalizedMessage());
		}catch(Exception e){
			this.setError(e.toString());
			context.log(this.getClass().getName() + " - Method:doGetAllCharacters: "  + e.getMessage());
		}
		finally{
	    	try{stmt.close();}catch(Exception ex){};
	        try{con.close();}catch(Exception ex){};
		}
    }
	
	
	/**
	 * 
	 * @param account - LoginName
	 * @throws SQLException
	 */
	protected void doDeleteAccount(String account) throws SQLException
	    {
			try{
	        con = dao.getDataSourceConnection(getContext());
	        
	        // Check Account Exist
	        PreparedStatement statement = con.prepareStatement("SELECT COUNT(*) FROM accounts WHERE login=?;");
	        statement.setString(1, account);
	        ResultSet rset = statement.executeQuery();
	        if(rset.next()==false)
	        {
	            System.out.println("False");
	            rset.close();
	        }
	        else if(rset.getInt(1)>0) 
	        {
	            rset.close();
	            // Account exist
	            
	            // Get Accounts ID
	            ResultSet rcln;
	            statement = con.prepareStatement("SELECT charId, char_name, clanid FROM characters WHERE account_name=?;");
	            statement.setEscapeProcessing(true);
	            statement.setString(1, account);
	            rset = statement.executeQuery();
	            
	            FastList<String> objIds = new FastList<String>();
	            FastList<String> charNames = new FastList<String>();
	            FastList<String> clanIds = new FastList<String>();
	            
	            while (rset.next())
	            {
	                objIds.add(rset.getString("charId"));
	                charNames.add(rset.getString("char_name"));
	                clanIds.add(rset.getString("clanid"));
	            }
	            rset.close();
	            
	            for (int index = 0; index < objIds.size(); index++)
	            {
	                System.out.println("Deleting character " + charNames.get(index) + ".");
	                
	                // Check If clan leader Remove Clan and remove all from it
	                statement.close();
	                statement = con.prepareStatement("SELECT COUNT(*) FROM clan_data WHERE leader_id=?;");
	                statement.setString(1, clanIds.get(index));
	                rcln = statement.executeQuery();
	                rcln.next();
	                if(rcln.getInt(1)>0) 
	                {
	                    rcln.close();
	                    // Clan Leader
	                    
	                    // Get Clan Name
	                    statement.close();
	                    statement = con.prepareStatement("SELECT clan_name FROM clan_data WHERE leader_id=?;");
	                    statement.setString(1, clanIds.get(index));
	                    rcln = statement.executeQuery();
	                    rcln.next();
	                    
	                    String clanName = rcln.getString("clan_name");
	                    
	                    System.out.println("Deleting clan " + rcln.getString("clan_name") + ".");
	                    
	                    // Delete Clan Wars
	                    statement.close();
	                    statement = con.prepareStatement("DELETE FROM clan_wars WHERE clan1=? OR clan2=?;");
	                    statement.setEscapeProcessing(true);
	                    statement.setString(1, clanName);
	                    statement.setString(2, clanName);
	                    statement.executeUpdate();
	                    
	                    rcln.close();
	                    
	                    // Remove All From clan
	                    statement.close();
	                    statement = con.prepareStatement("UPDATE characters SET clanid=0 WHERE clanid=?;");
	                    statement.setString(1, clanIds.get(index));
	                    statement.executeUpdate();
	                    // Free Clan Halls
	                    statement.close();
	                    statement = con.prepareStatement("UPDATE clanhall SET ownerId=0, paidUntil=0, paid=0 WHERE ownerId=?;");
	                    statement.setString(1, clanIds.get(index));
	                    statement.executeUpdate();
	                    // Delete Clan
	                    statement.close();
	                    statement = con.prepareStatement("DELETE FROM clan_data WHERE clan_id=?;");
	                    statement.setString(1, clanIds.get(index));
	                    statement.executeUpdate();
	                    //Clan privileges
	                    statement.close();
	                    statement = con.prepareStatement("DELETE FROM clan_privs WHERE clan_id=?;");
	                    statement.setString(1, clanIds.get(index));
	                    statement.executeUpdate();
	                    //Clan subpledges
	                    statement.close();
	                    statement = con.prepareStatement("DELETE FROM clan_subpledges WHERE clan_id=?;");
	                    statement.setString(1, clanIds.get(index));
	                    statement.executeUpdate();
	                    //Clan skills
	                    statement.close();
	                    statement = con.prepareStatement("DELETE FROM clan_skills WHERE clan_id=?;");
	                    statement.setString(1, clanIds.get(index));
	                    statement.executeUpdate();
	                    
	                    
	                }
	                else
	                    rcln.close();
	                
	                // skills
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_skills WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // skills save
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_skills_save WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // subclasses
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_subclasses WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // shortcuts
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_shortcuts WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // items
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM items WHERE owner_id=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // recipebook
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_recipebook WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // quests
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_quests WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // macroses
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_macroses WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // friends
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_friends WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // merchant_lease
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM merchant_lease WHERE player_id=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // boxaccess
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM boxaccess WHERE charname=?;");
	                statement.setString(1, charNames.get(index));
	                statement.executeUpdate();
	                
	                // hennas
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_hennas WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // recommends
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM character_recommends WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // characters
	                statement.close();
	                statement = con.prepareStatement("DELETE FROM characters WHERE charId=?;");
	                statement.setString(1, objIds.get(index));
	                statement.executeUpdate();
	                
	                // TODO: delete pets, olympiad/noble/hero stuff
	            }
	            
	            // Delete Account
	            statement.close();
	            statement = con.prepareStatement("DELETE FROM accounts WHERE login=?;");
	            statement.setEscapeProcessing(true);
	            statement.setString(1, account);
	            statement.executeUpdate();
	            
	            System.out.println("Account " + account + " has been deleted.");
	        } else {
	            // Not Exist
	            System.out.println("Account " + account + " does not exist.");
	        }
	        
	        // Close Connection
	        statement.close();
	        con.close();
	        
	    }catch(SQLException SQLe){
			context.log(this.getClass().getName() + " - Method:doGetAllCharacters: "  + SQLe.getLocalizedMessage());
			this.setError(SQLe.getLocalizedMessage());
		}catch(Exception e){
			this.setError(e.toString());
			context.log(this.getClass().getName() + " - Method:doGetAllCharacters: "  + e.getMessage());
		}
		finally{
	    	try{stmt.close();}catch(Exception ex){};
	        try{con.close();}catch(Exception ex){};
		}
	    }
	
	
	
	
}
